﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Green.FastInvoker;
using Green.Utility;

namespace Green.AgileMapper
{
    public class DefaultObjectMapper<From, To> : DefaultObjectMapper, IObjectMapper<From, To>
    {
        public DefaultObjectMapper(IMappingConfigurator mappingConfigurator)
            : base(mappingConfigurator)
        {

        }

        public From Warp(To to)
        {
            return (From)Warp(typeof(From), to);
        }

        public void Warp(From from, To to)
        {
            Warp(typeof(To), from, to);
        }


        public IList<From> Warp(IList<To> to)
        {
            List<From> froms = new List<From>();
            to.ToList().ForEach(t =>
            {
                froms.Add(Warp(t));
            });
            return froms;
        }

        public void Warp(IList<From> form, IList<To> to, Func<From, To, bool> equalPredicate)
        {
            Warp(form, to, equalPredicate, false);
        }

        public void Warp(IList<From> form, IList<To> to)
        {
            Warp(form, to, this.MappingConfigurator.DefaultEqualExpression, false);
        }

        public void Warp(IList<From> form, IList<To> to, bool isDeleteNotInFromItem)
        {
            Warp(form, to, this.MappingConfigurator.DefaultEqualExpression, isDeleteNotInFromItem);
        }

        public void Warp(IList<From> form, IList<To> to, Func<From, To, bool> equalPredicate, bool isDeleteNotInFromItem)
        {
            Warp(form, to, new Func<object, object, bool>((f, t) => equalPredicate((From)f, (To)t)), isDeleteNotInFromItem);
        }

        protected void Warp(IList<From> form, IList<To> to, Func<object, object, bool> equalPredicate, bool isDeleteNotInFromItem)
        {
            if (form == null)
                return;

            if (to == null)
            {
                to = new List<To>();
            }

            form.ToList().ForEach(f =>
            {
                To toItem = default(To);
                if (equalPredicate != null)
                {
                    toItem = to.ToList().SingleOrDefault(t => equalPredicate(f, t));
                }
                if (toItem == null)
                {
                    toItem = (To)Activator.CreateInstance(typeof(To));
                    to.Add(toItem);
                }
                Warp(f, toItem);
            });

            if (isDeleteNotInFromItem)
            {
                to.Where(t => form.FirstOrDefault(f => equalPredicate(f, t)) == null)
                    .ToList().ForEach(t =>
                    {
                        to.Remove(t);
                    });
            }
        }

        public string CodeGenerator(From fromObj)
        {
            return CodeGenerator(typeof(From), typeof(To), fromObj);
        }

        public string CodeGenerator()
        {
            return CodeGenerator((From)Activator.CreateInstance(typeof(From)));
        }
    }
}
